package vip.liux.backend.application.service.messaging;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.liux.application.dots.ListResultDto;
import vip.liux.backend.infrastructure.code.BizCodeGenerator;
import vip.liux.contracts.infrastructure.messaging.MessageBus;
import vip.liux.contracts.infrastructure.messaging.MessageTemplateValueObj;
import vip.liux.contracts.models.notification.MessageTemplate;
import vip.liux.contracts.repositories.messaging.MessageTemplateRepository;
import vip.liux.contracts.shared.enums.Status;

import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class MessageTemplateService {

    // 定义一个正则表达式，用于匹配内容中的变量占位符，例如 {{ variableName }}
    private static final Pattern VARIABLE_PATTERN = Pattern.compile("\\{\\{\\s*\\w+\\s*}}");

    @Autowired
    private MessageTemplateRepository notificationPolicyRepository; // 通知策略的数据库操作接口

    @Autowired
    private BizCodeGenerator bizCodeGenerator; // 用于生成策略编码的工具类

    /**
     * 创建通知策略
     *
     * @param input 包含通知策略信息的 Dto
     * @return 创建成功的通知策略 Dto
     */
    public MessageTemplateValueObj create(CreateNotificationPolicyDto input) {
        // 校验 content 字段中是否包含变量占位符，并检查这些变量是否在变量列表中定义
        Matcher matcher = VARIABLE_PATTERN.matcher(input.getContent());

        while (matcher.find()) {
            // 提取变量占位符的内容，例如 {{ variableName }} -> variableName
            String variable = matcher.group();
            String variableName = variable.substring(2, variable.length() - 2).trim();

            // 如果变量名为空，抛出异常
            if (variableName.isEmpty()) {
                throw new IllegalArgumentException("变量名不能为空");
            }

            // 如果变量名未在变量列表中定义，抛出异常
            if (!input.getVariables().containsKey(variableName)) {
                throw new IllegalArgumentException("变量名" + variableName + "未在变量列表中定义");
            }
        }

        // 将输入的 Dto 转换为实体对象
        MessageTemplate template = AutoMapperProfile.INSTANCE.toEntity(input);

        // 生成策略编码并设置到实体对象中
        template.setTemplateCode(bizCodeGenerator.generateTemplateCode());

        // 保存实体对象到数据库，并将保存后的实体对象转换为 Dto
        MessageTemplateValueObj templateDto = AutoMapperProfile.INSTANCE.toDto(notificationPolicyRepository.save(template));

        // 将新创建的策略添加到消息总线中进行观察
        observation(templateDto);

        // 返回创建成功的策略 Dto
        return templateDto;
    }

    /**
     * 根据策略编码查询通知策略列表
     *
     * @param code 策略编码
     * @return 包含通知策略的列表结果 Dto
     */
    public ListResultDto<MessageTemplateValueObj> list(String code) {
        // 查询数据库中所有匹配策略编码的通知策略，并转换为 Dto 列表
        return new ListResultDto<>(AutoMapperProfile.INSTANCE.toDtoList(
                notificationPolicyRepository.findAllByTemplateCode(code))
        );
    }

    /**
     * 修改通知策略的状态（启用或禁用）
     *
     * @param code   策略编码
     * @param enable 是否启用
     */
    @Transactional
    public void changeStatus(String code, boolean enable) {
        // 根据 ID 查询通知策略，如果不存在则抛出异常
        notificationPolicyRepository.findAllByTemplateCode(code).forEach(t -> {

            // 设置策略状态为启用或禁用
            t.setStatus(enable ? Status.ENABLED : Status.DISABLED);

            // 保存修改后的策略到数据库，并将其添加到消息总线中进行观察
            observation(AutoMapperProfile.INSTANCE.toDto(notificationPolicyRepository.save(t)));
        });

    }

    /**
     * 将通知策略添加到消息总线中进行观察
     *
     * @param dto 通知策略的 Dto
     */
    protected void observation(MessageTemplateValueObj dto) {
        // 初始化消息总线，将策略 Dto 添加到总线中
        MessageBus.init(Collections.singletonList(dto));
    }
}